package com.fqy.ticket.generator.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.fqy.ticket.generator.enums.SqlType;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DbUtil {

    public static String url = "";
    public static String user = "";
    public static String password = "";

    public static Connection getConnection() {
        Connection conn = null;
        // 使用完后关闭连接
        try {
            // 加载MySQL JDBC驱动类
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = DbUtil.url;
            String user = DbUtil.user;
            String password = DbUtil.password;
            conn = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 获得表注释
     * @param tableName
     * @return
     * @throws Exception
     */
    public static String getTableComment(String tableName) throws Exception {
        // // 获取连接
        // Connection conn = getConnection();
        // // 创建Statement对象用于执行SQL
        // Statement stmt = conn.createStatement();
        // ResultSet rs = stmt.executeQuery("select table_comment from information_schema.tables Where table_name = '" + tableName + "'");
        // String tableNameCH = "";
        // if (rs != null) {
        //     while(rs.next()) {
        //         tableNameCH = rs.getString("table_comment");
        //         break;
        //     }
        // }
        // rs.close();
        // stmt.close();
        // conn.close();
        // System.out.println("表名：" + tableNameCH);
        // return tableNameCH;
        // SQL查询语句：从information_schema系统表中获取表注释
        // table_schema = DATABASE() 确保只查询当前连接的数据库
        // 对传入的参数用?，会被单引号包裹
        String sql = "SELECT table_comment FROM information_schema.tables " +
                "WHERE table_name = ? AND table_schema = DATABASE()";

        // 使用try-with-resources自动关闭数据库连接、Statement和ResultSet，倒序关闭
        try (Connection conn = getConnection();  // 获取数据库连接
             PreparedStatement pstmt = conn.prepareStatement(sql)) {  // 创建预编译语句

            // 设置SQL参数：将tableName绑定到第一个占位符?
            pstmt.setString(1, tableName);

            // 执行查询并处理结果集, 通过try catch关闭
            try (ResultSet rs = pstmt.executeQuery()) {
                // rs.next()判断是否有下一行数据（表存在时返回true）
                if (rs.next()) {
                    System.out.println("表名：" + rs.getString("table_comment"));
                    // 获取当前行的table_comment列值（即表注释）
                    return rs.getString("table_comment");
                }
                // 表不存在时，rs.next()返回false，进入下一行代码
            }
        } catch (SQLException e) {
            // 发生SQL异常时打印堆栈信息（生产环境建议记录日志）
            e.printStackTrace();
        }

        // 默认返回空字符串（表不存在或发生异常时）
        return "";
    }

    /**
     * 获得所有列信息
     * @param tableName
     * @return
     * @throws Exception
     */
    public static List<Field> getColumnByTableName(String tableName) throws Exception {
        List<Field> fieldList = new ArrayList<>();

        try (Connection conn = getConnection();
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SHOW FULL COLUMNS FROM `" + tableName + "`")) {

            // 约定是rs永远不会为null，可以为空
            while (rs.next()) {
                String columnName = rs.getString("Field");
                String type = rs.getString("Type");
                String comment = rs.getString("Comment");
                boolean nullable = "YES".equals(rs.getString("Null"));

                Field field = new Field();
                field.setName(columnName);
                field.setNameHump(lineToHump(columnName));
                field.setNameBigHump(lineToBigHump(columnName));
                field.setType(type);
                field.setJavaType(DbUtil.sqlTypeToJavaType(type));
                field.setComment(comment);

                // 解析注释中的中文名（如果有分隔符）
                field.setNameCn(comment.contains("|")
                        ? comment.substring(0, comment.indexOf("|"))
                        : comment);

                field.setNullAble(nullable);

                // 解析VARCHAR长度
                if (type.toUpperCase().contains("VARCHAR")) {
                    try {
                        int length = Integer.parseInt(
                                type.substring(type.indexOf("(") + 1, type.indexOf(")"))
                        );
                        field.setLength(length);
                    } catch (Exception e) {
                        field.setLength(0); // 默认值
                        System.err.printf("解析字段长度失败 [%s]: %s%n", columnName, e.getMessage());
                    }
                }

                // 解析枚举信息
                if (comment.contains("枚举")) {
                    int start = comment.indexOf("[");
                    int end = comment.indexOf("]");
                    if (start != -1 && end != -1 && start < end) {
                        String enumName = comment.substring(start + 1, end);
                        String enumConst = StrUtil.toUnderlineCase(enumName)
                                .toUpperCase()
                                .replace("_ENUM", "");
                        field.setEnums(true);
                        field.setEnumsConst(enumConst);
                    } else {
                        field.setEnums(false);
                        System.err.printf("解析枚举格式失败 [%s]: %s%n", columnName, comment);
                    }
                }

                fieldList.add(field);
            }
        } catch (SQLException e) {
            System.err.printf("数据库操作失败 [%s]: %s%n", tableName, e.getMessage());
            e.printStackTrace();
        } catch (Exception e) {
            System.err.printf("处理表结构数据失败 [%s]: %s%n", tableName, e.getMessage());
            e.printStackTrace();
        }
        System.out.println("列信息：" + JSONUtil.toJsonPrettyStr(fieldList));
        return fieldList;
        // List<Field> fieldList = new ArrayList<>();
        // Connection conn = getConnection();
        // Statement stmt = conn.createStatement();
        // ResultSet rs = stmt.executeQuery("show full columns from `" + tableName + "`");
        // if (rs != null) {
        //     while(rs.next()) {
        //         String columnName = rs.getString("Field");
        //         String type = rs.getString("Type");
        //         String comment = rs.getString("Comment");
        //         String nullAble = rs.getString("Null"); //YES NO
        //         Field field = new Field();
        //         field.setName(columnName);
        //         field.setNameHump(lineToHump(columnName));
        //         field.setNameBigHump(lineToBigHump(columnName));
        //         field.setType(type);
        //         field.setJavaType(DbUtil.sqlTypeToJavaType(rs.getString("Type")));
        //         field.setComment(comment);
        //         if (comment.contains("|")) {
        //             field.setNameCn(comment.substring(0, comment.indexOf("|")));
        //         } else {
        //             field.setNameCn(comment);
        //         }
        //         field.setNullAble("YES".equals(nullAble));
        //         if (type.toUpperCase().contains("varchar".toUpperCase())) {
        //             // varchar设置的长度
        //             String lengthStr = type.substring(type.indexOf("(") + 1, type.length() - 1);
        //             field.setLength(Integer.valueOf(lengthStr));
        //         } else {
        //             field.setLength(0);
        //         }
        //         if (comment.contains("枚举")) {
        //             field.setEnums(true);
        //
        //             // 以课程等级为例：从注释中的“枚举[CourseLevelEnum]”，得到enumsConst = COURSE_LEVEL
        //             int start = comment.indexOf("[");
        //             int end = comment.indexOf("]");
        //             String enumsName = comment.substring(start + 1, end); // CourseLevelEnum
        //             String enumsConst = StrUtil.toUnderlineCase(enumsName)
        //                     .toUpperCase().replace("_ENUM", "");
        //             field.setEnumsConst(enumsConst);
        //         } else {
        //             field.setEnums(false);
        //         }
        //         fieldList.add(field);
        //     }
        // }
        // rs.close();
        // stmt.close();
        // conn.close();
        // System.out.println("列信息：" + fieldList);
        // return fieldList;
    }

    /**
     * 下划线转小驼峰：member_id 转成 memberId
     */
    public static String lineToHump(String str){
        String res = str.toLowerCase().replaceAll("_+", "_");
        Pattern pattern = Pattern.compile("_(\\w)");
        Matcher matcher = pattern.matcher(res);
        res = matcher.replaceAll(matchResult -> matchResult.group(1).toUpperCase());
        return res;
        // Pattern linePattern = Pattern.compile("_(\\w)");
        // str = str.toLowerCase();
        // Matcher matcher = linePattern.matcher(str);
        // StringBuffer sb = new StringBuffer();
        // while(matcher.find()){
        //     matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        // }
        // matcher.appendTail(sb);
        // return sb.toString();
    }

    /**
     * 下划线转大驼峰：member_id 转成 MemberId
     */
    public static String lineToBigHump(String str){
        String s = lineToHump(str);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

    /**
     * 数据库类型转为Java类型
     */
    public static String sqlTypeToJavaType(String sqlType) {
        return SqlType.map(sqlType);
        // if (sqlType.toUpperCase().contains("varchar".toUpperCase())
        //         || sqlType.toUpperCase().contains("char".toUpperCase())
        //         || sqlType.toUpperCase().contains("text".toUpperCase())) {
        //     return "String";
        // } else if (sqlType.toUpperCase().contains("datetime".toUpperCase())) {
        //     return "Date";
        // } else if (sqlType.toUpperCase().contains("bigint".toUpperCase())) {
        //     return "Long";
        // } else if (sqlType.toUpperCase().contains("int".toUpperCase())) {
        //     return "Integer";
        // } else if (sqlType.toUpperCase().contains("long".toUpperCase())) {
        //     return "Long";
        // } else if (sqlType.toUpperCase().contains("decimal".toUpperCase())) {
        //     return "BigDecimal";
        // } else if (sqlType.toUpperCase().contains("boolean".toUpperCase())) {
        //     return "Boolean";
        // } else {
        //     return "String";
        // }
    }
}

